package com.yt.server.comm;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.mina.core.session.IoSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import com.yt.server.api.StatisticsCounter;
import com.yt.server.api.comm.ISession;
import com.yt.server.api.comm.ISessionManager;

/**
 * Session管理
 * 
 * @author 刘晶
 */
@Component
public class SessionManager implements ISessionManager, ApplicationContextAware {

	private static final Logger log = LoggerFactory
			.getLogger(SessionManager.class);

	private ApplicationContext appCtx = null;

	public static Random rnd = new Random();

	private static String destinationDirectory = null;

	private ReadWriteLock lock = new ReentrantReadWriteLock();

	private static AtomicLong sessionIdGenerator = new AtomicLong();

	protected final StatisticsCounter counter = new StatisticsCounter();

	private static ConcurrentMap<String, ISession> sessions = new ConcurrentHashMap<String, ISession>();

	@Override
	public ISession getSession(String id) {
		try {
			lock.readLock().lock();
			if (sessions.get(id) != null)
				return sessions.get(id);
		} finally {
			lock.readLock().unlock();
		}
		return null;
	}

	@Override
	public ISession createSession(IoSession ioSession) {
		lock.writeLock().lock();
		String id = getSessionId();
		try {
			if (!containsSession(id)) {
				// 建立Session
				counter.increment();
				ISession session = new Session(id, ioSession);
				session.setDestinationDirectory(destinationDirectory);
				sessions.put(id, session);
				return session;
			}
		} finally {
			lock.writeLock().unlock();
		}
		return null;
	}

	@Override
	public ISession removeSession(String id) {
		lock.writeLock().lock();
		try {
			if (containsSession(id)) {
				counter.decrement();
				getSession(id).end();
				return sessions.remove(id);
			}
		} finally {
			lock.writeLock().unlock();
		}
		return null;
	}

	@Override
	public Collection<ISession> removeSessions() {
		ArrayList<ISession> sessionList = new ArrayList<ISession>(
				sessions.size());
		lock.writeLock().lock();
		try {
			sessionList.addAll(sessions.values());
			return sessionList;
		} finally {
			lock.writeLock().unlock();
		}
	}

	@Override
	public boolean containsSession(String id) {
		lock.readLock().lock();
		try {
			if (sessions.get(id) != null)
				return true;
		} finally {
			lock.readLock().unlock();
		}
		return false;
	}

	@Override
	public void setApplicationContext(ApplicationContext arg0)
			throws BeansException {
		this.appCtx = arg0;
	}

	@Override
	public StatisticsCounter getCounter() {
		return counter;
	}

	@Override
	public void setDestinationDirectory(String destinationDir) {
		SessionManager.destinationDirectory = destinationDir;
	}

	public static String getSessionId() {
		int part1 = rnd.nextInt(99999) + 1;
		long part2 = sessionIdGenerator.incrementAndGet();
		long part3 = System.currentTimeMillis();
		String sessionId = createHash(part1 + "-" + part2 + "-" + part3);
		log.debug("Session id created: {}", sessionId);
		return sessionId;
	}

	public static String createHash(String str) {
		return DigestUtils.md5Hex(str.getBytes());
	}
}